<?php

/*
	Class: Install

	About: Author
		J William McCarthy

	About: License
		<http://communit.as/docs/license>

	About: See Also
		<App_Controller_Action_Abstract>
*/
 class InstallController extends Zend_Controller_Action{

	/* Group: Instance Methods */

	/*
		Function: init
			Invoked automatically when an instance is created.
			Initializes the current instance.
			Also initializes the parent object (calls init() on the parent instance).

		Registry Values:
			theme_global_path - TBD
			theme_url - TBD
	*/
	function init(){
		parent::init();
		$this->view->theme_global = Zend_Registry::get('theme_global_path');
		$this->view->theme_url = Zend_Registry::get('theme_url');
		$this->view->site_name = "communit.as";
				
	}

	/* Group: Actions */

	/*
		Function: finished
			Displays when the installation has finished.
	*/
	
	function secondstageAction(){
				$request = new App_Request($this->getRequest());
				$appNamespace = new Zend_Session_Namespace('App_Temp');
				
				$basepath = Zend_Registry::get('basepath');
				$config_table = new Config();
				$config_table->set('default','upload_path',$basepath."/uploads",true);
				$config_table->set('default','theme','default',true);
				$config_table->set('default','missing_image',$basepath."/themes/default/images/image-missing.png",true);
				$config_table->cache();					
				
				$username = $request->username;
				$users_table = new Users();
				$user = $users_table->fetchByUsername($username);
				$password = substr(md5(rand(50000,100000)),0,8);				
				
				if(!is_null($user)){					
					$user->password = $password;
					$user->save();
					$users_table->setMetaData($username,"is_installer",1);
					
					$appNamespace->autoLogin = true;
	        		$appNamespace->autoLoginUsername = $username;
	        		$appNamespace->autoLoginPassword = md5($password);
													
				} else {
					die("Dammit. Somehow the admin user didn't get created or didn't get sent with the request. This is bad. Really, really bad.");
				}
				$this->_redirect("/install/finished/username/".$username);
				
	}
	
	function finishedAction(){
		$request = new App_Request($this->getRequest());
		$username = $request->username;
				$users_table = new Users();
				$user = $users_table->fetchByUsername($username);
				$password = substr(md5(rand(50000,100000)),0,8);				
				
				if(!is_null($user)){					
					$user->password = $password;
					$user->save();
					$this->view->username = $username;
					$this->view->password = $password;
					
	        		// we should never need this again, so we remove access to it.
	        		$roles_resources_table = new RolesResources();
	        		$where  = $roles_resources_table->getAdapter()->quoteInto("module = ? ","default");
	        		$where .= $roles_resources_table->getAdapter()->quoteInto(" and controller = ? ","Install");
	        		$roles_resources_table->delete($where);
															
				} else {
					die("Dammit. Somehow the admin user didn't get created or didn't get sent with the request. This is bad. Really, really bad.");
				}
	}

	/*
		Function: index
			Displays the Communitas installer.

		View Variables:
			$admin_email - TBD
			$admin_password - TBD
			$admin_username - TBD
			$app_asido_path - TBD
			$app_smarty_path - TBD
			$app_timezone - TBD
			$app_zf_path - TBD
			$db_host - TBD
			$db_name - TBD
			$db_user - TBD
			$db_pass - TBD
			$db_port - TBD
			$db_sock - TBD
			$errors - An array of error messages. Only exists if errors occurred.
			$smarty_cache_dir - TBD
			$smarty_compile_dir - TBD
	*/
	function indexAction(){
		$request = new App_Request($this->getRequest());
		$basepath = Zend_Registry::get('basepath');
		$this->view->timezones = App_Common::getTimeZonesArray();

		if($this->getRequest()->isPost()){
			$errors = array();
			
			/*
			 * TODO: Check that smarty dirs are writeable, etc. dir is writable, etc. dir is NOT writeable after install, libraries exist,
			 * log level is set to something
			 */
			
			if(!file_exists($basepath . "/.htaccess")){
				$errors[] = "Missing .htaccess file in ". $basepath . ". Maybe use ".$basepath."/template.htaccess ?";
			}			
			
			$zf_version_class = $request->app_zf_path."/Zend/Version.php";
			$smarty_class_file = $request->app_smarty_path . "/Smarty.class.php" ;
			$asido_class_file = $request->app_asido_path. "/class.asido.php";
			$etc_dir = $basepath . "/etc";
			$config_filename = $etc_dir . "/config.ini";
			$tmp_path			= $request->tmp_path;
			$smarty_compile_dir = $tmp_path."/view_compiles";			
			$smarty_cache_dir 	= $tmp_path."/cache";
			$image_cache_dir	= $tmp_path."/image_cache";
			$upload_path		= $basepath."/uploads";
			$log_path			= $request->log_path;
			
			
			if(!file_exists($zf_version_class)){
				$errors[] = "Can't find Zend Framework in ".$request->app_zf_path;
			} else {				
				require_once($zf_version_class);
				if(Zend_Version::compareVersion(App_Versions::ZF) > 0){
					$errors[] = "Communit.as requires Zend Framework ".App_Versions::ZF." or higher. The supplied version is ".Zend_Version::VERSION.".";
				}
			}
			
			if(!file_exists($smarty_class_file)){
				$errors[] = "Can't find Smarty in ".$request->app_smarty_path;
			} else {				
				
				$smarty_class_lines = explode("\n",file_get_contents($smarty_class_file));
				$strVersion = "* @version";
				foreach($smarty_class_lines as $line){
					
					if(strpos($line,$strVersion) !== false){
						$found_smarty_version = trim(substr($line,strpos($line,$strVersion) + strlen($strVersion)));
						break;
					}
				}
				
				if(version_compare(App_Versions::SMARTY,$found_smarty_version) > 0){
					$errors[] = "Communit.as requires Smarty Template Engine ".App_Versions::SMARTY." or higher. The supplied version is ".$found_smarty_version.".";
				}
			}
			
			
			if(!file_exists($asido_class_file)){
				$errors[] = "Can't find Asido in ".	$request->app_asido_path . ".";
			} else {
				require_once($asido_class_file);
				$asido = new Asido();
				if(version_compare(App_Versions::ASIDO,$asido->version()) > 0){
					$errors[] = "Communit.as requires Asido ".App_Versions::ASIDO." or higher. The supplied version is ".$asido->version().".";
				}
			}
			
			$dir_array = array($etc_dir,
				$tmp_path,
				$upload_path,
				$log_path
				);
			
		
			foreach($dir_array as $dir){
				if(!is_writable($dir)){
					$errors[] = "Web server can't write to ".$dir.".";
				}	
			}
	
			if($request->admin_username == null){
				$errors[] = "Admin username cannot be blank.";				
			}

			if($request->admin_email == null){
				$errors[] = "Admin email cannot be blank.";				
			}

			$cfg_array = array(
				"database" => array(
					"adapter" 	=> "PDO_MYSQL",
					"params"	=> array(
					"host" 		=> $request->db_host,
					"dbname" 	=> $request->db_name,			
					"username" 	=> $request->db_user,
					"password" 	=> $request->db_pass,
					"port" 		=> $request->db_port,
					)
				)
			);

			if(!is_null($request->db_sock)){
				$cfg_array['database']['params']['unix_socket'] = $request->db_sock;  // this is often something like /var/run/mysqld/mysqld.sock
			}

			$dbconfig = new Zend_Config($cfg_array);			

			$db = Zend_Db::factory($dbconfig->database);

			try{
				if(count($errors) == 0){
					$tables = $db->listTables();
					if(count($tables) > 0){
						$errors[] = "The specified database is not empty.";
					}

					// get the table creation script
					$ddl_file = $basepath . "/modules/default/sql/" . $dbconfig->database->adapter . "/install.sql";
					if(file_exists($ddl_file)){
						$queries = explode(";",file_get_contents($ddl_file));
						$db->beginTransaction();

						try{
							foreach($queries as $query){
								if(trim($query) != ""){
									$query = str_replace("@@@@ADMIN_USERNAME@@@@", $request->admin_username, $query);									
									$query = str_replace("@@@@ADMIN_EMAIL@@@@", $request->admin_email, $query);
									$query = str_replace("@@@@CREATED_ON@@@@@", date("Y-m-d H:i:s"), $query);
									$db->query($query);
								}
							}						

							$db->commit();

						} catch (Exception $e) {
							$db->rollBack();
							$errors[] = $e->getMessage();
						}				
					} else {
						$errors[] = "Database creation script not found.";
					}
				}
			} catch (Exception $e) {
				$errors[] = $e->getMessage();	
			}			

			if(count($errors) == 0){
				// everything worked out okay, attempt to write the config file

				$config = array(
					"db.communitas.adapter" 		=> "PDO_MYSQL", // This should really be configurable, but it isn't yet.
					"db.communitas.config.host" 	=> $request->db_host,
					"db.communitas.config.dbname" 	=> $request->db_name,			
					"db.communitas.config.username" => $request->db_user,
					"db.communitas.config.password" => $request->db_pass,
					"db.communitas.config.port" 	=> $request->db_port,
					"db.communitas.config.default" 	=> "true",
				);
				if(!is_null($request->db_sock)){
					$config['db.communitas.config.unix_socket'] = $request->db_sock;
				}
				$config_file .= App_ConfigFile::makeSection("databases", "Database Settings", "This is the default database.", $config);
				
				$app_config = array(
					"timezone"			=> $request->app_timezone,
					"launched" 			=> "1",
					"prelaunch_url" 	=> "http://google.com",
					"allowed_ips"		=> "127.0.0.1",					
					"zf_path" 			=> $request->app_zf_path,
					"smarty_path" 		=> $request->app_smarty_path,
					"asido_path" 		=> $request->app_asido_path,
					"image_cache_dir"	=> $image_cache_dir,
					"log_filename"		=> $log_path."/app_log",
					"log_level"			=> "6",
					"addtl_includes"	=> "",
				);

				$config_file .= App_ConfigFile::makeSection("application", "Application Settings", "These are the application specific settings.", $app_config);

				// create directories if needed
				if(!file_exists($smarty_compile_dir)){				
					mkdir($smarty_compile_dir,0777,true);
				}
				
				if(!file_exists($smarty_cache_dir)){
					mkdir($smarty_cache_dir,0777,true);
				}
				
				if(!file_exists($image_cache_dir)){
					mkdir($image_cache_dir,0777,true);
				}
				
				$smarty_config = array(
					"config.compile_dir" 	=> $smarty_compile_dir,
					"config.cache_dir" 		=> $smarty_cache_dir,
				);

				$config_file .= App_ConfigFile::makeSection("smarty", "Smarty Settings", "These are the settings for the Smarty template engine.", $smarty_config);

				$plugin_cfg_array = array(
					";Index_Plugin" => 10,					
				);

				$config_file .= App_ConfigFile::makeSection("plugins","Plugin Settings","Plugins should be configured here. Each line should be a valid class that implements the plugin interface. The numeric value after each classname is the priority, which should be 10 unless you have a reason for it not to be.",$plugin_cfg_array);

				if(file_put_contents($config_filename,$config_file) === false){
					$this->view->config_file = $config_file;
					$this->view->config_filename = $config_filename;
					$this->view->success = "Database installed, but could not write config file. Please create the file \"".$config_filename."\" and paste this following into it:";
				} else {
					$this->_redirect("/install/secondstage/username/".$request->admin_username);
				}			

			} else {
				$this->view->errors 	= $errors;
				$this->view->db_host 	= $request->db_host;
				$this->view->db_name 	= $request->db_name;
				$this->view->db_user 	= $request->db_user;
				$this->view->db_pass 	= $request->db_pass;
				$this->view->db_port 	= $request->db_port;
				$this->view->db_sock 	= $request->db_sock;
				$this->view->admin_username		= $request->admin_username;
				$this->view->admin_password		= $request->admin_password;
				$this->view->admin_email		= $request->admin_email;
				$this->view->app_timezone 		= $request->app_timezone;
				$this->view->app_zf_path 		= $request->app_zf_path;
				$this->view->app_smarty_path 	= $request->app_smarty_path;
				$this->view->app_asido_path 	= $request->app_asido_path;
				$this->view->tmp_path			= $request->tmp_path;
				$this->view->log_path			= $request->log_path;
				
			}

		} else {
			$this->view->db_host = "localhost";
			$this->view->db_name = "communitas";
			$this->view->db_user = "root";
			$this->view->db_pass = "";
			$this->view->db_port = "3306";
			$this->view->db_sock = "";
			$this->view->admin_username		= "admin";				
			$this->view->app_timezone 		= "America/Los_Angeles";
			$this->view->app_zf_path 		= $basepath."/lib/ZendFramework/library";
			$this->view->app_smarty_path 	= $basepath."/lib/Smarty/libs";
			$this->view->app_asido_path 	= $basepath."/lib/Asido";			
			$this->view->tmp_path			= $basepath."/tmp";			
			$this->view->log_path			= $basepath."/logs";
			 						
		}			
		
	}

}
